package session.stateless;


import entity.AccessRightsEntity;
import entity.StaffAccountEntity;
import entity.StaffEntity;
import exception.ExistException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import util.entityhelper.StaffAccountState;
import util.enumeration.AccessRight;
import util.enumeration.Country;
import util.enumeration.Department;
import util.enumeration.Gender;
import util.enumeration.JobPosition;
import util.generator.PasswordGenerator;

/**
 *
 * @author AdminNUS
 */
@Stateless
public class StaffAccountManagerBean implements StaffAccountManagerLocal {
    @PersistenceContext
    EntityManager em;
    
    private String selectedLocale;

    private StaffEntity staffEntity;
    private StaffAccountEntity staffAccountEntity;
    
    // EXCEPTION
    private SystemMessagesLocal systemMessages;

    /** Creates a new instance of TouristAccountManagerBean */
    public StaffAccountManagerBean() {
        
    }
    
    @Override
    public void setSelectedLocale(String locale) {
        this.selectedLocale = locale;
    }

    @Override
    public void createStaffAccount(String username, // username = primary email
                                    String lastName, String firstName, 
                                    Gender gender, Date birthdate, 
                                    Country country, String locale, 
                                    String email, String emailSecondary,
                                    Department department, JobPosition jobPosition,
                                    Date joinDate, List<AccessRight> accessRights) throws ExistException {
        
        // tourist user account entity does not exist;
        if (staffAccountEntity == null && staffEntity == null) {
            staffAccountEntity = new StaffAccountEntity();
            staffEntity = new StaffEntity();
            
            staffEntity.create(lastName, firstName, gender, birthdate, country, locale, email, emailSecondary, department, jobPosition, joinDate);
            
            // auto get system time for registration date
            Calendar cal = Calendar.getInstance();
            Date creationDate = cal.getTime();
            Date passwordChangeDate = cal.getTime();
            // access rights
            List<AccessRightsEntity> newAccessRights = new ArrayList<AccessRightsEntity>();
            for (AccessRight ar : accessRights) {
                AccessRightsEntity newAccessRight = new AccessRightsEntity();
                newAccessRight.setAccessRight(ar);
                newAccessRights.add(newAccessRight);
            }
            // password is auto-generated from PasswordGenerator
            PasswordGenerator generator = new PasswordGenerator();
            // assume min length is 6
            String password = generator.generatePassword(6);
            staffAccountEntity.create(username, password, creationDate, passwordChangeDate);
            staffAccountEntity.setAccessRights(newAccessRights);
            
            staffAccountEntity.setStaff(staffEntity);
            em.persist(staffAccountEntity);
        }
        else {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_EXISTS", selectedLocale));
        }
    }
    
    @Override
    public void updateStaffAccount(Long staffAccountId, String newPassword, List<AccessRight> accessRights) throws ExistException {
        // find account in persistence context
        staffAccountEntity = em.find(StaffAccountEntity.class, staffAccountId);
        
        // tourist user account entity does not exist;
        if (staffAccountEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            // reset access rights
            List<AccessRightsEntity> newAccessRights = new ArrayList<AccessRightsEntity>();
            for (AccessRight ar : accessRights) {
                AccessRightsEntity newAccessRight = new AccessRightsEntity();
                newAccessRight.setAccessRight(ar);
                newAccessRights.add(newAccessRight);
            }
            staffAccountEntity.getAccessRights().clear();
            staffAccountEntity.setAccessRights(newAccessRights);
            
            String password = staffAccountEntity.getPassword();
            Date passwordChangeDate = staffAccountEntity.getPasswordChangeDate();
            if (!password.equals(newPassword)) {
                // auto get system time for registration date
                Calendar cal = Calendar.getInstance();
                passwordChangeDate = cal.getTime();
            }
            staffAccountEntity.update(newPassword, passwordChangeDate);
            
            em.persist(staffAccountEntity);
            em.flush();
        }
    }
    
    @Override
    public void updateStaff(Long staffId, Country country, String locale, String email, String emailSecondary, Department department, JobPosition jobPosition) throws ExistException {
        // find tourist in persistence context
        staffEntity = em.find(StaffEntity.class, staffId);
        
        // tourist entity does not exist;
        if (staffEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            staffEntity.update(country, locale, email, emailSecondary, department, jobPosition);
            em.persist(staffEntity);
            em.flush();
        }
    }
    
    @Override
    public StaffAccountState getStaffAccountByID(Long staffUserAccountId) throws ExistException {
        StaffAccountState staffUserAccountState = null;

        // find account id
        Query q = em.createQuery("SELECT a FROM StaffAcct a WHERE a.id = :accId");
        q.setParameter("accId", staffUserAccountId);

        if (q.getResultList().isEmpty()) {
            // show exception message using SystemMessage bean
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            StaffAccountEntity a = (StaffAccountEntity)q.getSingleResult();
            staffUserAccountState = new StaffAccountState(
                    a.getId(),
                    a.getUsername(),
                    a.getPassword(),
                    a.getCreationDate(),
                    a.getPasswordChangeDate(),
                    a.getStatus(),
                    a.getAccessRights(),
                    a.getStaff());
        }
        return staffUserAccountState;
    }
    
    @Override
    public StaffAccountState getStaffAccountByUsername(String username) // is primary email..
            throws ExistException {
        StaffAccountState staffAccountState = null;

        // find username
        Query q = em.createQuery("SELECT a FROM StaffAcct a WHERE a.username = :uname");
        q.setParameter("uname", username);

        // result has nothing...
        if (q.getResultList().isEmpty()) {
            // show exception message using SystemMessage bean
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        // if result has something...
        else {
//            // get access rights list
//            Query qAccessRightsEntity = em.createQuery("SELECT b FROM OperatingHours b where b.branch.id =:branchId and b.id NOT IN (select ex.id from ExtendedOperatingHours ex)");
//            qAccessRightsEntity.setParameter("branchId", branchId);
//            
//            if (qAccessRightsEntity.getResultList().isEmpty()) {
//                // set list to null?
//            }
//            else {
//                
//            }
            StaffAccountEntity a = (StaffAccountEntity)q.getSingleResult();
            System.out.println(a.getUsername() + "" + a.getPassword());
            staffAccountState = new StaffAccountState(
                    a.getId(),
                    a.getUsername(),
                    a.getPassword(),
                    a.getCreationDate(),
                    a.getPasswordChangeDate(),
                    a.getStatus(),
                    a.getAccessRights(),
                    a.getStaff());
        }
        return staffAccountState;
    }
    
    @Override
    public List<StaffAccountState> getTCubeAccountList() {
        List<StaffAccountState> TCubeList = new ArrayList();
        System.out.println("TCubeSesion1");

        Query query = em.createQuery("SELECT a FROM StaffAcct a");
        List<StaffAccountState> accountList = query.getResultList();
        System.out.println("Size: " + accountList.size());
        StaffAccountState t = null;
        for (int i = 0; i < accountList.size(); i++) {
            if (accountList.get(i).getClass().getName().equalsIgnoreCase("entity.StaffAcct")) {
                t = (StaffAccountState) query.getSingleResult();
                TCubeList.add(t);
            }
        }
        return TCubeList;
    }
    
    @Override
    public void updateStatus(StaffAccountState user) {
        StaffAccountEntity s = em.find(StaffAccountEntity.class, user.getId());
        if (s != null) {
            s.setStatus(user.getStatus());
            em.persist(s);
            em.flush();
        }
    }

    
    
//    public Set<StudentDetailsState> getStudents() throws ExistException {
//        Query q = em.createQuery("SELECT s FROM Student s");
//        Set stateSet = new HashSet();
//
//        if (q.getResultList().isEmpty()) {
//            throw new ExistException("No students found in database!");
//        }
//        else {
//            for (Object o: q.getResultList()) {
//                StudentEntity s = (StudentEntity)o;
//                StudentDetailsState sdState = new StudentDetailsState(
//                        s.getStdId(), s.getName(),
//                        s.getAddress().getAddId(),
//                        s.getAddress().getAddressLine1(),
//                        s.getAddress().getAddressLine2(),
//                        s.getAddress().getPostalCode(),
//                        s.getContactNumber().getCttId(),
//                        s.getContactNumber().getPhoneNumber());
//                stateSet.add(sdState);
//            }
//        }
//        return stateSet;
//    }

//    public Set<StudentDetailsState> getStudentOrStudentsByName(String name)
//            throws ExistException {
//        Set stateSet = new HashSet();
//        StudentDetailsState sdState = null;
//
//        // find name in database before creation
//        Query q = em.createQuery("SELECT s FROM Student s WHERE s.name = :sName");
//        q.setParameter("sName", name);
//
//        if (q.getResultList().isEmpty()) {
//            throw new ExistException("No such student found in database!");
//        }
//        else {
//            // only 1 person with the specified name
//            if (q.getResultList().size() == 1) {
//                StudentEntity s = (StudentEntity)q.getSingleResult();
//                sdState = new StudentDetailsState(
//                        s.getStdId(), s.getName(),
//                        s.getAddress().getAddId(),
//                        s.getAddress().getAddressLine1(),
//                        s.getAddress().getAddressLine2(),
//                        s.getAddress().getPostalCode(),
//                        s.getContactNumber().getCttId(),
//                        s.getContactNumber().getPhoneNumber());
//                stateSet.add(sdState);  // add only 1
//            }
//            // if 2 or more people have the same name, return the list for user to choose
//            else if (q.getResultList().size() > 1) {
//                for (int i = 0; i < q.getResultList().size(); i++) {
//                    StudentEntity s = (StudentEntity)q.getResultList().get(i);
//                    sdState = new StudentDetailsState(
//                            s.getStdId(), s.getName(),
//                            s.getAddress().getAddId(),
//                            s.getAddress().getAddressLine1(),
//                            s.getAddress().getAddressLine2(),
//                            s.getAddress().getPostalCode(),
//                            s.getContactNumber().getCttId(),
//                            s.getContactNumber().getPhoneNumber());
//                    stateSet.add(sdState);
//                }
//            }
//        }
//        return stateSet;
//    }
    
    @Override
    public void deleteStaffAccount(Long staffAccountId)
        throws ExistException {

        staffAccountEntity = em.find(StaffAccountEntity.class, staffAccountId);

        // tourist user account entity does not exist;
        if (staffAccountEntity == null) {
            // EXCEPTION
            throw new ExistException(systemMessages.getSystemMessage("STAFF_ACCT_DOES_NOT_EXIST", selectedLocale));
        }
        else {
            staffEntity = em.find(StaffEntity.class, staffAccountEntity.getStaff().getId());
//            if (staffAccountEntity.getRegistrations().size() > 0) {
//                throw new ExistException("Student has already registered.");
//            }
//
//            contactNumberEntity = studentEntity.getContactNumber();
//            addressEntity = studentEntity.getAddress();
//
//            em.remove(contactNumberEntity);
            em.remove(staffEntity);
            em.remove(staffAccountEntity);
        }
    }

    @Override
    @Remove
    public void remove() {
        System.out.println("StaffAccountManagerBean:remove()");
    }
}
